package com.bestcem.xm.ticket.service.manager.notify;

import cn.hutool.json.JSONUtil;
import com.bestcem.xm.componet.sms.SmsService;
import com.bestcem.xm.openplatform.grpc.v1.services.FeiShuEnterpriseInfo;
import com.bestcem.xm.ticket.grpc.client.*;
import com.bestcem.xm.ticket.grpc.client.dto.openPlatform.FeiShuEnterpriseInfoDTO;
import com.bestcem.xm.ticket.grpc.client.dto.user.SmtpDTO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import javax.annotation.Resource;
import javax.mail.internet.MimeMessage;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 工单消息发送 工具类
 *
 * @author XiaoYunSong <ys.xiao@idiaoyan.com>
 * @version v1.0
 * @date 2021/9/19 14:39
 */
@Slf4j
@Component
public class NotifyManager {

    @Value("${app.ticket.debug:false}")
    private Boolean debug;

    //默认邮箱，配置文件中的spring.mail
    @Resource
    private JavaMailSender springDefaultMailSender;

    @Resource
    private TicketDingTalkGrpcService ticketDingTalkGrpcService;
    @Resource
    private TicketCommonGrpcService ticketCommonGrpcService;

    @Resource
    private SmsService smsService;

    @Resource
    private TicketBaseOpenPlatformGrpcService ticketBaseOpenPlatformGrpcService;
    @Resource
    private TicketWechatGrpcService ticketWechatGrpcService;

    @Resource
    private TicketBaseUserGrpcService ticketBaseUserGrpcService;


    private JavaMailSenderImpl getMailSender(SmtpDTO smtp) {
        try (Socket socket = new Socket()) {
            socket.connect(new InetSocketAddress(smtp.getHost(), Integer.parseInt(smtp.getPort())), 1000);
        } catch (IOException e) {
            log.error("邮箱域名:{},端口:{} 无效 ;", smtp.getHost(), smtp.getPort());
        }

        JavaMailSenderImpl sender = new JavaMailSenderImpl();
        sender.setProtocol("smtp");
        sender.setHost(smtp.getHost().trim());
        sender.setUsername(smtp.getAccount());
        sender.setPassword(smtp.getPassword());
        sender.setDefaultEncoding("UTF-8");
        Properties properties = new Properties();
        // 设置超时时间
        properties.setProperty("mail.smtp.timeout", "5000");
        // 如果是ssl的话,需要设置以下属性
        if (Boolean.TRUE.equals(smtp.isSSL())) {
            properties.setProperty("mail.smtp.auth", "true");
            properties.setProperty("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");
            properties.setProperty("mail.smtp.socketFactory.port", String.valueOf(smtp.getPort()));
        }
        sender.setJavaMailProperties(properties);
        return sender;
    }

    /**
     * 通用发送邮件
     *
     * @param receiveUsers 收件人邮箱列表
     * @param ccUsers      抄送人邮箱列表
     * @param subject      主题
     * @param content      内容
     * @param smtpId       发件箱
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/9/19 14:42
     */
    public void sendEmail(@Nonnull Collection<String> receiveUsers, @Nullable Collection<String> ccUsers,
                          @Nonnull String subject, @Nonnull String content, String smtpId, SmtpDTO smtp) {
        if (log.isInfoEnabled()) {
            log.info("[Ticket] Global sendEmail 接收人:{};抄送人:{};主题:{};\n 内容:{};邮箱id:{};\n邮箱smtp:{}", receiveUsers, ccUsers, subject, content, smtpId, JSONUtil.toJsonStr(smtp));
        }
        if (!org.springframework.util.StringUtils.hasText(smtpId) && smtp == null) {
            log.error("[ticket] NotifyManager sendEmail smtpId smtp 必须要有一个");
            return;
        }
        if (!CollectionUtils.isEmpty(receiveUsers)) {
            // 去掉列表中的null
            receiveUsers = receiveUsers.stream().filter(Objects::nonNull).collect(Collectors.toList());
            if (CollectionUtils.isEmpty(receiveUsers)) {
                log.error("[ticket] NotifyManager sendEmail 收件人不能为空");
            }
        }
        if (!CollectionUtils.isEmpty(ccUsers)) {
            // 去掉列表中的null
            ccUsers = ccUsers.stream().filter(Objects::nonNull).collect(Collectors.toList());
        }

        JavaMailSenderImpl mailSender;
        if (Objects.nonNull(smtp)) {
            mailSender = getMailSender(smtp);
        } else {
            SmtpDTO userSmtp = ticketBaseUserGrpcService.getSmtpById(smtpId);
            if (Objects.isNull(userSmtp)) {
                log.error("没有找到对应的[{}]用户邮箱,临时使用配置邮箱", smtpId);
                mailSender = (JavaMailSenderImpl) springDefaultMailSender;
            } else {
                mailSender = getMailSender(userSmtp);
            }
        }
        try {
            MimeMessage message = mailSender.createMimeMessage();
            MimeMessageHelper helper = new MimeMessageHelper(message, true, String.valueOf(StandardCharsets.UTF_8));
            //收件人
            helper.setTo(receiveUsers.toArray(new String[0]));
            if (!CollectionUtils.isEmpty(ccUsers)) {
                //抄送人
                helper.setCc(ccUsers.toArray(new String[0]));
            }
            //主题
            helper.setSubject(subject);
            //内容
            helper.setText(content, true);
            helper.setFrom(Objects.requireNonNull(mailSender.getUsername()));
            mailSender.send(message);
        } catch (Exception e) {
            log.error("[ticket] NotifyManager sendEmail Exception");
            throw new RuntimeException(e);
        }
    }


    /**
     * 通用发送短信
     *
     * @param orgId    组织id
     * @param surveyId 问卷id
     * @param userName 奖励名称
     * @param content  发送对象 手机号
     * @param phone    短信发送内容
     * @param type     短信任务码
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/9/19 14:51
     */
    public void sendSms(@Nonnull String orgId, String surveyId, String userName,
                        @Nonnull String content, @Nonnull String phone, int type) {
        if (log.isInfoEnabled()) {
            log.info("[Ticket] Global sendSms {};{};{};\n{};{};{}", orgId, surveyId, userName, content, phone, type);
        }

        // 测试不真实发送短信
        if (debug) {
            log.error("[Ticket] Global sendSms 发送短信 {}-{}", phone, content);
            return;
        }
        //ticketCommonGrpcService.sendSmsNotice(orgId, surveyId, userName, content, phone, type);
        smsService.sendSms(phone, content, null);
    }


    /**
     * 根据组织code发送飞书
     *
     * @param orgCode 组织code
     * @param email   邮箱
     * @param content 内容
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/9/23 15:00
     */
    public void sendFeiShuByOrgCode(@Nonnull String orgCode, @Nonnull String email, @Nonnull String content) {
        if (log.isInfoEnabled()) {
            log.info("[Ticket] Global sendFeiShuByOrgCode {};{}", orgCode, email);
        }

        // 根据 orgCode 获取企业飞书信息
        FeiShuEnterpriseInfoDTO feiShuEnterpriseInfoDTO = getTenantKeyBuyOrgCode(orgCode);
        if (Objects.isNull(feiShuEnterpriseInfoDTO)) {
            log.error("[Ticket] Global sendFeisuByOrgCode {} 组织获取飞书信息失败", orgCode);
            return;
        }

        String tenantKey = feiShuEnterpriseInfoDTO.getTenantKey();
        String tenantAppId = feiShuEnterpriseInfoDTO.getTenantAppid();
        String tenantAppSecret = feiShuEnterpriseInfoDTO.getTenantAppsecret();

        // 发送飞书
        sendFeiShu(tenantKey, tenantAppId, tenantAppSecret, email, content);
    }


    /**
     * 通用发送飞书
     *
     * @param tenantKey       租户密钥
     * @param tenantAppId     租户 appid
     * @param tenantAppSecret 租户 应用密钥
     * @param email           邮箱
     * @param content         内容
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/9/23 15:00
     */
    public void sendFeiShu(@Nonnull String tenantKey, @Nonnull String tenantAppId, @Nonnull String tenantAppSecret,
                           @Nonnull String email, @Nonnull String content) {
        if (log.isInfoEnabled()) {
            log.info("[Ticket] Global sendFeiShu {};{};{};{};\n{}", tenantKey, tenantAppId, tenantAppSecret, email, content);
        }

        if (!ObjectUtils.isEmpty(email)) {
            // 发送飞书
            ticketCommonGrpcService.sendFeiShuNotice(tenantKey, tenantAppId, tenantAppSecret, email, content);
        }
    }


    /**
     * 通用发送钉钉
     *
     * @param receiveUsers 收件人userId列表
     * @param templateId   钉钉通知模板id
     * @param params       钉钉通知模板变量, JSON字符串
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/9/19 14:42
     */
    public void sendDingTalk(@Nonnull Collection<String> receiveUsers, @Nonnull String templateId, @Nonnull String params) {
        if (log.isInfoEnabled()) {
            log.info("[Ticket] Global sendDingTalk {};{};{}", receiveUsers, templateId, params);
        }

        if (!CollectionUtils.isEmpty(receiveUsers)) {
            // 去掉列表中的null
            receiveUsers = receiveUsers.stream().filter(Objects::nonNull).collect(Collectors.toList());
            ticketDingTalkGrpcService.sendTemplateMessage(receiveUsers, templateId, params);
        }
    }

    /**
     * 通用发送企业微信
     *
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2021/9/19 14:42
     */
    public void sendWechatWork(String orgId, @Nonnull Collection<String> receiveUsers,
                               String page, String title, String description, Map<String, String> contentItem) {
        if (log.isInfoEnabled()) {
            log.info("[Ticket] Global sendWechatWork {};{};{};{};{};{}", orgId, receiveUsers, page, title, description, contentItem);
        }

        if (!CollectionUtils.isEmpty(receiveUsers)) {
            // 去掉列表中的null
            receiveUsers = receiveUsers.stream().filter(Objects::nonNull).collect(Collectors.toList());
            // 发送企业微信通知; 开启重复消息检查, 10s 内不能发送重复的消息, 防止消息刷屏
            ticketCommonGrpcService.sendWechatWorkNotice(orgId, receiveUsers, null, null, page, title, description,
                    contentItem, false, 0, 1, 10);
        }
    }


    /**
     * 通用发送微信公众号模板消息
     *
     * @param openIds    接收消息的 微信openId 列表
     * @param templateId 微信公众号模板id
     * @param params     微信公众号模板自定义参数(JSON)
     * @param url        跳转链接
     * @author XiaoYunSong <ys.xiao@idiaoyan.com>
     * @date 2022/4/20 10:15
     */
    public void sendWechatPublic(@Nonnull Collection<String> openIds, @Nonnull String templateId
            , @Nonnull String params, @Nullable String url) {
        if (log.isInfoEnabled()) {
            log.info("[Ticket] Global sendWechatPublic {};{};{};{}", openIds, templateId, params, url);
        }

        if (!CollectionUtils.isEmpty(openIds)) {
            // 去掉列表中的null
            openIds = openIds.stream().filter(Objects::nonNull).collect(Collectors.toList());
            // 发送微信公众号模板消息
            ticketWechatGrpcService.sendTemplateMessage(openIds, templateId, params, url);
        }
    }


    // ==================== private method ====================


    /**
     * 根据机构号码获取租户信息
     *
     * @param orgCode
     * @return String
     * @version v1.0
     * @author gy.liu
     * @date 2021/9/2
     */
    private FeiShuEnterpriseInfoDTO getTenantKeyBuyOrgCode(String orgCode) {
        try {
            FeiShuEnterpriseInfo.Builder builder = FeiShuEnterpriseInfo.newBuilder();
            builder.setOrgCode(orgCode);
            List<FeiShuEnterpriseInfoDTO> feiShuEnterpriseInfoDTOS =
                    ticketBaseOpenPlatformGrpcService.listFeiShuEnterpriseInfo(builder.buildPartial(), null, null, null);
            if (Objects.nonNull(feiShuEnterpriseInfoDTOS) && feiShuEnterpriseInfoDTOS.size() > 0) {
                return feiShuEnterpriseInfoDTOS.get(0);
            }
        } catch (Exception e) {
            log.error("NOTIFY getTenantKeyBuyOrgCode failed", e);
            return null;
        }
        return null;
    }
}
